#include "head.h"

// 航班信息表-双向循环链表的操作函数定义
//  双向链表的创建
f_list *init_double_link_list()
{
    // 1、创建动态空间
    f_list *list = (f_list *)malloc(sizeof(f_list));
    // 安全判断
    if (NULL == list)
    {
        ERRLOG("航班信息-双向循环链表动态创建空间失败!");
        return NULL;
    }
    // 2、初始化赋值
    list->next = NULL;
    // 3、返回list
    return list;
}

// 双向链表的插入
void insert_double_node(f_list *list, f_data data, int pos)
{
    // 安全判断
    if (NULL == list)
    {
        ERRLOG("航班信息-双向循环链表为NULL!");
        return;
    }
    // 创建数据结点
    f_node *new_node = (f_node *)malloc(sizeof(f_node));
    if (NULL == new_node)
    {
        ERRLOG("创建动态空间失败");
        return;
    }
    // 结点初始化
    new_node->data = data;
    new_node->next = new_node;
    new_node->prev = new_node;
    // 头插
    if (1 == pos || NULL == list->next)
    {
        // 内部有数据的头插
        if (1 == pos && NULL != list->next)
        {
            // 1 指向 第一个结点
            f_node *ptr = list->next;
            // 2 将 ptr 的 prev 的 next 指向 新结点
            ptr->prev->next = new_node;
            // 3 new_node 的 next 指向 ptr
            new_node->next = ptr;
            // 4 new_node 的 prev 指向 ptr 的 prev
            new_node->prev = ptr->prev;
            // 5 ptr 的 prev 指向 new_node
            ptr->prev = new_node;
            // 6 头结点 指向 新结点
            list->next = new_node;
            flight_data_file_print(list); // 写入到文件
            return;
        }
        // 内部无数据的头插    内部无数据 默认 头插
        if (NULL == list->next)
        {
            list->next = new_node;
            flight_data_file_print(list); // 写入到文件
            return;
        }
    }

    // 中间插入(尾插)
    // 查找插入结点前一个结点
    f_node *ptr = find_double_node_pos(list, pos - 1);

    // 判断插入的位置是否合法
    if (pos < 1 || NULL == ptr)
    {
        ERRLOG("插入的位置非法!");
        return;
    }

    // 开始插入
    // 1、 新结点的 next 指向 ptr的next
    new_node->next = ptr->next;
    // 2、 ptr next prev 指向 新结点
    ptr->next->prev = new_node;
    // 3、 新结点 prev 指向 ptr
    new_node->prev = ptr;
    // 4、 ptr next 指向 new_node
    ptr->next = new_node;
    flight_data_file_print(list); // 写入到文件
    return;
}


// 双向链表的插入(不写入文件版)
void insert_node_normal(f_list *list, f_data data, int pos)
{
    // 安全判断
    if (NULL == list)
    {
        ERRLOG("航班信息-双向循环链表为NULL!");
        return;
    }
    // 创建数据结点
    f_node *new_node = (f_node *)malloc(sizeof(f_node));
    if (NULL == new_node)
    {
        ERRLOG("创建动态空间失败");
        return;
    }
    // 结点初始化
    new_node->data = data;
    new_node->next = new_node;
    new_node->prev = new_node;
    // 头插
    if (1 == pos || NULL == list->next)
    {
        // 内部有数据的头插
        if (1 == pos && NULL != list->next)
        {
            // 1 指向 第一个结点
            f_node *ptr = list->next;
            // 2 将 ptr 的 prev 的 next 指向 新结点
            ptr->prev->next = new_node;
            // 3 new_node 的 next 指向 ptr
            new_node->next = ptr;
            // 4 new_node 的 prev 指向 ptr 的 prev
            new_node->prev = ptr->prev;
            // 5 ptr 的 prev 指向 new_node
            ptr->prev = new_node;
            // 6 头结点 指向 新结点
            list->next = new_node;
            return;
        }
        // 内部无数据的头插    内部无数据 默认 头插
        if (NULL == list->next)
        {
            list->next = new_node;
            return;
        }
    }

    // 中间插入(尾插)
    // 查找插入结点前一个结点
    f_node *ptr = find_double_node_pos(list, pos - 1);

    // 判断插入的位置是否合法
    if (pos < 1 || NULL == ptr)
    {
        ERRLOG("插入的位置非法!");
        return;
    }

    // 开始插入
    // 1、 新结点的 next 指向 ptr的next
    new_node->next = ptr->next;
    // 2、 ptr next prev 指向 新结点
    ptr->next->prev = new_node;
    // 3、 新结点 prev 指向 ptr
    new_node->prev = ptr;
    // 4、 ptr next 指向 new_node
    ptr->next = new_node;
    return;
}

// 双向循环链表的删除
    void delete_double_node(f_list *list, int pos)
{
    // 安全判断
    is_empty_double_link_list(list);
    // 删除
    f_node *ptr_1 = list->next;  // 用于删除结点
    f_node *ptr_2 = ptr_1->next; // 用于遍历结点

    // 头删  情况 1、 pos == 1  2、只有一个元素  ptr_1->next == list->nexts
    if (1 == pos || ptr_1->next == list->next)
    {
        // 只有一个结点数据的时候
        if (1 != pos && ptr_1->next == list->next)
        {
            free(ptr_1);       // 直接释放ptr_1
            list->next = NULL; // 头结点置空
            flight_data_file_print(list); // 写入到文件
            return;
        }

        // 多个结点数据删第一个
        if (1 == pos)
        {
            // 1、 将头结点 指向 第二个 结点
            list->next = ptr_2;
            // 2、 将 ptr2 指向 尾结点
            ptr_2->prev = ptr_1->prev;
            // 3、 将尾结点 的 指向 第二个结点
            ptr_1->prev->next = ptr_2;
            // 4、 释放 ptr 1
            free(ptr_1);
            flight_data_file_print(list); // 写入到文件
            return;
        }
    }
    // 任意位置删除
    // 先查找到删除结点前一个结点
    ptr_1 = find_double_node_pos(list, pos - 1);
    // 如果ptr_1回到了头节点，说明链表长度不够，无法删除指定位置的节点
    if (pos < 1 || NULL == ptr_1)
    {
        ERRLOG("删除的位置非法!");
        return;
    }
    ptr_2 = ptr_1->next;
    // 只有最后一个结点的删除
    if (list->next == ptr_1->next)
    {
        list->next = NULL;
        free(ptr_2);
        flight_data_file_print(list); // 写入到文件
        return;
    }

    // 1、 将ptr_1 指向 ptr_2的next结点
    ptr_1->next = ptr_2->next;
    // 2、 将 ptr2 的next的prev指向ptr1
    ptr_2->next->prev = ptr_1;
    // 3、 释放 ptr 2
    free(ptr_2);
    flight_data_file_print(list); // 写入到文件
    return;
}

// 双向链表的查找
// 按位置查找
f_node *find_double_node_pos(f_list *list, int pos)
{
    // 安全判断
    is_empty_double_link_list(list);
    f_node *p = list->next; // 用于变量查找
    for (int i = 1; i < pos; i++)
    {
        p = p->next;
        // 循环遍历完一趟还没有找到该结点
        if (pos != 1 && list->next == p) // 排除pos为1的情况
        {
            // ERRLOG("查找的位置非法!");
            return NULL;
        }
    }
    return p;
}
// 按起始站-终点站查找
void find_double_node_location(f_list *list, char *start_city, char *arrive_city)
{
    system("clear");
    // 安全判断
    is_empty_double_link_list(list);
    f_node *p = list->next; // 用于变量查找
    printf("班次    机型            起点站         终点站           起飞时间        到达时间        飞行时间       票价           载客量         剩余座位    是否起飞\n");
    printf("----------------------------------------------------------------------------------------------------------------------------------------------------------------------\n");
    do
    {
        // 判断起始站和终点站是否都相等
        if (!(strcmp(p->data.startcity, start_city)) && !(strcmp(p->data.arrivecity, arrive_city)))
        {
            print_flight_1(p);
        }
        p = p->next;
    } while (p != list->next);
    // 循环遍历完一趟还没有找到该结点
    if ((strcmp(p->data.startcity, start_city)) || (strcmp(p->data.arrivecity, arrive_city)))
    {
        // text_center("抱歉,暂无这两地之间的航班,请重新输入!\n", RED);
        return ;
    }
}

// 判断是否有该班次航班
f_node *is_find_location(f_list *list, char *start_city, char *arrive_city)
{
    // 安全判断
    is_empty_double_link_list(list);
    f_node *p = list->next; // 用于变量查找
    do
    {
        // 判断起始站和终点站是否都相等
        if (!(strcmp(p->data.startcity, start_city)) && !(strcmp(p->data.arrivecity, arrive_city)))
        {
            print_flight_1(p);
            return p;
        }
        p = p->next;
        return p;
    } while (p != list->next);
    // 循环遍历完一趟还没有找到该结点
    if ((strcmp(p->data.startcity, start_city)) || (strcmp(p->data.arrivecity, arrive_city)))
    {
        // printf("抱歉,暂无%s——%s之间的航班!\n", start_city, arrive_city);
        return NULL;
    }
}

// 根据班次查找
f_node *find_double_node_id(f_list *list, int *id)
{
    // 安全判断
    is_empty_double_link_list(list);
    f_node *p = list->next; // 用于变量查找
    do
    {
        // 判断起始站和终点站是否都相等
        if (*id==p->data.id)
        {
            return p;
        }
        p = p->next;
    } while (p != list->next);
    // 循环遍历完一趟还没有找到该结点
    return NULL;
}



// 双向链表的遍历
void print_forward_double_link_list(f_list *list,int sleep_time)
{
    if (NULL == list)
    {
        ERRLOG("双向循环链表 为 NULL");
        return;
    }
    if (NULL == list->next)
    {
        ERRLOG("双向循环链表 无 数据");
        return;
    }
    system("clear");
    time_t current_time;
    time(&current_time);
    struct tm *l_time = localtime(&current_time);
    printf("                                                                    %s现在是北京时间:", YELLOW);
    printf("%s%d年%d月%d日——", YELLOW, l_time->tm_year + 1900, l_time->tm_mon + 1, l_time->tm_mday);
    printf("%s%d时%d分%d秒\n", YELLOW, l_time->tm_hour, l_time->tm_min, l_time->tm_sec);
    text_frame("今日航班", CYAN);
    printf("班次    机型            起点站         终点站           起飞时间        到达时间        飞行时间       票价           载客量         剩余座位    是否起飞\n");
    printf("----------------------------------------------------------------------------------------------------------------------------------------------------------------------\n");

    f_node *ptr = list->next;
    do
    {
        printf("%-6d\t", ptr->data.id);
        printf("%s\t\t", ptr->data.flighttype);
        printf("%s\t\t", ptr->data.startcity);
        printf("%s\t\t", ptr->data.arrivecity);
        printf("%02d:%02d\t\t", ptr->data.starttime[0], ptr->data.starttime[1]);
        printf("%02d:%02d\t\t", ptr->data.arrivetime[0], ptr->data.arrivetime[1]);
        printf("%s\t\t", ptr->data.flytime);
        printf("%d\t\t", ptr->data.value);
        printf("%d\t\t", ptr->data.maxNUM);
        printf("%d\t  ", ptr->data.leftbuyersa);
        printf("   %c\n", ptr->data.whetherfly);
        ptr = ptr->next;
        sleep(sleep_time);  //刷新时间
    } while (ptr != list->next);
    char ch = ' ';
    while (10 != ch)
    {
        sleep(1); // 当前进程进入休眠态 S
        ch = getchar();
    }
    return;
}

void print_backwards_double_link_list(f_list *list);
// 双向链表的判空
void is_empty_double_link_list(f_list *list)
{
    // 安全判断
    if (NULL == list)
    {
        ERRLOG("航班信息-双向循环链表为NULL!");
        return;
    }

    if (NULL == list->next)
    {
        ERRLOG("航班信息-双向循环链表数据为空!");
        return;
    }
}

// 双向链表的清空
void clear_double_link_list(f_list *list)
{
    // 安全判断
    if (NULL == list)
    {
        ERRLOG("航班信息-双向循环链表为NULL!");
        return;
    }

    if (NULL == list->next)
    {
        ERRLOG("航班信息-双向循环链表数据已为空!");
        return;
    }

    // 释放结点
    f_node *p1 = list->next;
    f_node *p2 = p1->next;
    while (list->next != p1)
    {
        free(p1);
        p1 = p2;
        p2 = p2->next;
    }
    list->next = NULL; // 头结点置空
    puts("航班信息-双向循环链表数据已清空!");
    return;
}

// 双向链表的合并
f_list *merge_double_link_lists(f_list *list1, f_list *list2);
// 双向链表的销毁(需要传二级指针才能销毁头结点)
void free_double_link_list(f_list **list)
{
    // 安全判断
    if (NULL == list)
    {
        ERRLOG("航班信息-双向循环链表为NULL!");
        return;
    }

    if (NULL == (*list)->next)
    {
        ERRLOG("航班信息-双向循环链表数据为空!");
        // 释放头结点
        free(*list);
        return;
    }

    // 释放结点
    f_node *p1 = (*list)->next;
    f_node *p2 = p1->next;
    while ((*list)->next != p1)
    {
        free(p1);
        p1 = p2;
        p2 = p2->next;
    }
    // 释放头结点
    free(*list);
    *list = NULL;
    puts("航班信息-双向循环链表已销毁!");
    return;
}

// 打印一条航班数据
void print_flight_1(f_node *p)
{
    printf("%-6d\t", p->data.id);
    printf("%s\t\t", p->data.flighttype);
    printf("%s\t\t", p->data.startcity);
    printf("%s\t\t", p->data.arrivecity);
    printf("%02d:%02d\t\t", p->data.starttime[0], p->data.starttime[1]);
    printf("%02d:%02d\t\t", p->data.arrivetime[0], p->data.arrivetime[1]);
    printf("%s\t\t", p->data.flytime);
    printf("%d\t\t", p->data.value);
    printf("%d\t\t", p->data.maxNUM);
    printf("%d\t  ", p->data.leftbuyersa);
    printf("   %c\n", p->data.whetherfly);
    return;
}